#include <p30F6010.h>
#include <can.h>

#define	MASCARA_RX	0x0030
#define	MASCARA_TX	0x0033

#define FCY 		20000000             		// 20 MHz
#define BITRATE 	1000000			 			// 1Mbps
#define NTQ 		8							// NUMERO DE CICLOS DE TQ PARA CUMPLIR CON EL REUQRIMIENTO DE 
												// TIEMPO EN EL PROTOCOLO CAN
#define TQ			(1/(BITRATE*NTQ))			// FORMULA UTILIZADA PARA CALCULAR LA PREESCASLA 
#define BRP_VAL		((2*TQ*FCY)-1)  			// Y CONFIGURAR EL REGISTRO C1CFG1bits.BRP

//---------------------------------------------------------------------
// BUFFER UTILIZADOS PARA ENVIAR DATOS

unsigned int OutData0 = 0;

// SE INICIAN EN O LOS BUFFER PARA RECIBIR DATOS
unsigned int 	InData0 = 0;
extern char    	pcAmarantaUartBufferTx[2];

//---------------------------------------------------------------------
void init_can1(void)
{
//--------------------------------------------------------------------------------------------------------------------
					// INICIALIZACION DEL MODULO CAN1 Y HABILITACION DE INTERRUPCIONES
//--------------------------------------------------------------------------------------------------------------------
 
 C1CTRLbits.CANCKS = 1;			// SELECCION DEL MASTER CLOCK PARA EL CAN. FCAN=FCY. 
								// (FCY=20Mhz)

 C1CFG1bits.SJW=00;				// SALTO DE SINCRONIZACION = 1 x TQ
 
 C1CFG1bits.BRP = BRP_VAL;		//((2*TQ*FCY)-1) 	

 C1CFG2 = 0x0290;               // PRSEG + SEG1PH >= SEG2PH 
                                // SEG2PH > SAMPLES TIME
								// PRSEG=1TQ, SEG1PH=3TQ, SEG2PH=3TQ, SAMPLE 1TQ
                                // TIEMPO DE BIT = 8TQ

///INTERRUPCION DEL PERIFERICO CAN1
 C1INTF = 0;					//RESET DE TODAS LAS INTERRUPCIONES DEL CAN 
 IFS1bits.C1IF = 0;  			//RESET DE LA BANDERA DE INTERRUPCIONES
 C1INTE = 0x0005;               //HABILITA LAS INTERRUPCIONES DEL CAN
 IEC1bits.C1IE = 1;				//HABILITA LAS INTERRUPCIONES DEL CAN1

//-----------------------------------------------------------------------------------------------------------------------
						// CONFIGURACION DEL REGISTRO DE RECEPCION, FILTROS Y MASCARAS
//-----------------------------------------------------------------------------------------------------------------------

// SE INICIALIZAN EL BUFFER 0 Y BUFFER 1 PARA LA RECEPCION DEL CAN1
 C1RX0CON =  0x0000; 	// CONFIGURACION DEL REGISTRO DE CONTROL Y STATUS DEL CAN1
 								// SE ESCOGEN LOS FILTROS 0 PARA EL BUFFER 0 Y EL BUFFER 1

// SE CONFIGURAN LAS MASCARAS SID PARA EL REGISTROS0 Y REGISTRO1 ASOCIADOS
// CON EL BUFFER0 Y BUFFER1 DEL CAN1 
 C1RXM0SID  =  0x1FFD; // SE HABILITA UNA UNICA IDENTIFICACION DE MENSAJES(SD O EID)
								   // SE TIENE EN CUENTA TODOS LOS BITS DE LA MASCARA

//INICIALIZACION DE LOS FILTROS DE ACEPTACION EN EL CAN1
 C1RXF0SID 	= MASCARA_RX<<2;	//CAN1 ACEPTACION DE RECIBO PARA EL FILTRO 0 SID = 1 
 C1RXF2SID 	= 0x1554;   		//CAN1 ACEPTACION DE RECIBO PARA EL FILTRO 2 SID = 555
 
 //-----------------------------------------------------------------------------------------------------------------------
						// CONFIGURACION DEL BUFFER0 Y BUFFER1 PARA LA TRANSMISION
//-----------------------------------------------------------------------------------------------------------------------
  
 C1TX0CON = 0x0003;     		// HIGH PRIORITY
 C1TX0SID = MASCARA_TX<<2;     	// SID = 0
 C1TX0DLC = 0x0010;				// SE SELECCIONAEL TAMA O DEL DATOS PARA TRANSMITIR POR EL CAN1 BUFFER 0 EN 8 BYTES  

//DATA FIELD1, DATA FIELD2, DATA FIELD3, DATA FIELD4 SELECCIONADOS EN DLC
 C1TX0B1 = OutData0;
 
  
//SE CAMBIA DEL MODO DE CONFIGURACION AL MODO DE LOOPBACK
 C1CTRLbits.REQOP = 0;
 while(C1CTRLbits.OPMODE != 0); // SE ESPERA A QUE SE CAMBIE DEL MODO CONFIGURACION AL MODO LOOPBACK, ESTO ES NECESARIO!!!!! 

}//FIN DEL INIT CAN


//--------------------------------------------------------------------------------------------------------------------
					// TRANSMISION CAN PATA 1
//--------------------------------------------------------------------------------------------------------------------
char Tx_can(unsigned char dato, unsigned int  mask_msg_tx)
{

//--------------------------------------------------------------------------------------------------------------------
					// INICIALIZACION DEL MODULO CAN1 Y HABILITACION DE INTERRUPCIONES
//--------------------------------------------------------------------------------------------------------------------
 
 C1CTRLbits.CANCKS = 1;			// SELECCION DEL MASTER CLOCK PARA EL CAN. FCAN=FCY. 
								// (FCY=20Mhz)

 C1CFG1bits.SJW=00;				// SALTO DE SINCRONIZACION = 1 x TQ
 
 C1CFG1bits.BRP = BRP_VAL;		//((2*TQ*FCY)-1) 	

 C1CFG2 = 0x0290;               // PRSEG + SEG1PH >= SEG2PH 
                                // SEG2PH > SAMPLES TIME
								// PRSEG=1TQ, SEG1PH=3TQ, SEG2PH=3TQ, SAMPLE 1TQ
                                // TIEMPO DE BIT = 8TQ

///INTERRUPCION DEL PERIFERICO CAN1
 C1INTF = 0;					//RESET DE TODAS LAS INTERRUPCIONES DEL CAN 
 IFS1bits.C1IF = 0;  			//RESET DE LA BANDERA DE INTERRUPCIONES
 C1INTE = 0x0005;               //HABILITA LAS INTERRUPCIONES DEL CAN
 IEC1bits.C1IE = 1;				//HABILITA LAS INTERRUPCIONES DEL CAN1

//-----------------------------------------------------------------------------------------------------------------------
						// CONFIGURACION DEL REGISTRO DE RECEPCION, FILTROS Y MASCARAS
//-----------------------------------------------------------------------------------------------------------------------

// SE INICIALIZAN EL BUFFER 0 Y BUFFER 1 PARA LA RECEPCION DEL CAN1
 C1RX0CON =  0x0000; 	// CONFIGURACION DEL REGISTRO DE CONTROL Y STATUS DEL CAN1
 								// SE ESCOGEN LOS FILTROS 0 PARA EL BUFFER 0 Y EL BUFFER 1

// SE CONFIGURAN LAS MASCARAS SID PARA EL REGISTROS0 Y REGISTRO1 ASOCIADOS
// CON EL BUFFER0 Y BUFFER1 DEL CAN1 
 C1RXM0SID  =  0x1FFD; // SE HABILITA UNA UNICA IDENTIFICACION DE MENSAJES(SD O EID)
								   // LA MASCARA DE BIT ES 0x7FF

//INICIALIZACION DE LOS FILTROS DE ACEPTACION EN EL CAN1
 C1RXF0SID 	= MASCARA_RX<<2;	//CAN1 ACEPTACION DE RECIBO PARA EL FILTRO 0 SID = 1 		
 C1RXF2SID 	= 0x1554;   		//CAN1 ACEPTACION DE RECIBO PARA EL FILTRO 2 SID = 555
 
//-----------------------------------------------------------------------------------------------------------------------
						// CONFIGURACION DEL BUFFER0 Y BUFFER1 PARA LA TRANSMISION
//-----------------------------------------------------------------------------------------------------------------------
  
 C1TX0CON = 0x0003;     		// HIGH PRIORITY
 C1TX0SID = mask_msg_tx<<2;     	// SID = 1
 C1TX0DLC = 0x0010;				// SE SELECCIONAEL TAMA O DEL DATOS PARA TRANSMITIR POR EL CAN1 BUFFER 0 EN 8 BYTES  

//DATA FIELD1, DATA FIELD2, DATA FIELD3, DATA FIELD4 SELECCIONADOS EN DLC
//DATA FIELD1, DATA FIELD2, DATA FIELD3, DATA FIELD4 SELECCIONADOS EN DLC
 C1TX0B1 = (unsigned int)dato;
  
//SE CAMBIA DEL MODO DE CONFIGURACION AL MODO DE LOOPBACK
 C1CTRLbits.REQOP = 0;
 while(C1CTRLbits.OPMODE != 0); // SE ESPERA A QUE SE CAMBIE DEL MODO CONFIGURACION AL MODO LOOPBACK, ESTO ES NECESARIO!!!!! 

//HABILITA LA TRANSMISION
 C1TX0CONbits.TXREQ = 1;        

}

//--------------------------------------------------------------------------------------------------------------------------
											//SUBRRUTINA DE INTERRUPCION CAN1
//--------------------------------------------------------------------------------------------------------------------------

void __attribute__((interrupt, no_auto_psv)) _C1Interrupt(void)
{
    if(C1INTFbits.TX0IF)
    {
		C1INTFbits.TX0IF = 0;  // SI LA INTERRUPCION FUE POR LA TRANSMISION DEL BUFFER0 EN CAN1, SE LIMPIA LA BANDERA DE INTERRUPCION
    }  

    if(C1INTFbits.RX0IF)
    {     
		C1RX0CONbits.RXFUL=0;    
		C1INTFbits.RX0IF = 0; 	// SI LA INTERRUPCION FUE POR LA RECEPCION DEL BUFFER0 EN CAN1, SE LIMPIA LA BANDERA DE INTERRUPCION

        InData0 = C1RX0B1; 		// SE COPIA EL EL DATO RECIBIDO EN INDATA

		pcAmarantaUartBufferTx[0]= (unsigned char)(InData0 & 0x00ff);
		pcAmarantaUartBufferTx[1]= (unsigned char)(InData0 >> 8);
		TxDat(1);                 	
    }
	IFS1bits.C1IF = 0;         //LIMPIA LA BANDERA DE INTERRUPCION CAN1
}
